package admin

import (
	"ecms/models"
	"ecms/utils/reflects"
	"ecms/utils/repository"
	"ecms/utils/response"
	"ecms/utils/tools"
	"ecms/utils/validator"
	"github.com/gin-gonic/gin"
	"time"
)

type DepartmentController struct {
}

// Index 部门列表
func (c *DepartmentController) Index(ctx *gin.Context) {
	departments := make([]models.AdminDepartment, 0)
	repo := repository.New(&models.AdminDepartment{})
	if !repo.SelectAll("sort ASC, updated_at DESC", &departments, "status = ? AND is_deleted = ?", 1, 0) {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	type treeAbleDepartment struct {
		Name        string        `json:"name"`
		Banner      string        `json:"banner"`
		Description string        `json:"description"`
		Sort        int64         `json:"sort"`
		UpdatedAt   response.Time `json:"updated_at"`
		tools.TreeAbleImplInt64
	}

	treeAbleDepartments := make([]tools.TreeAble, 0)
	for _, v := range departments {
		treeAbleDepartments = append(treeAbleDepartments, &treeAbleDepartment{
			Name:        v.Name,
			Banner:      v.Banner,
			Description: v.Description,
			Sort:        v.Sort,
			UpdatedAt:   v.UpdatedAt,
			TreeAbleImplInt64: tools.TreeAbleImplInt64{
				Id:       v.Id,
				Pid:      v.Pid,
				Children: make([]tools.TreeAble, 0),
			},
		})
	}

	response.SuccessJson(ctx, "查询成功", tools.TreeData(treeAbleDepartments, 0))
}

// Create 部门添加
func (c *DepartmentController) Create(ctx *gin.Context) {
	reqData := &models.AdminDepartment{
		IsDeleted: 0,
		Status:    1,
		CreatedAt: response.Time(time.Now().Local()),
		UpdatedAt: response.Time(time.Now().Local()),
	}
	rules := validator.NewRules(
		validator.NewRule("name", "部门名称", true, validator.TypeNoEmpty),
		validator.NewRule("banner", "部门Banner图", true, validator.TypeLink),
		validator.NewRule("description", "部门简介", false, validator.TypeNoEmpty),
		validator.NewRule("pid", "所属部门", true, validator.TypeNumber),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查重名
	hasSame := &models.AdminDepartment{}
	repo := repository.New(&models.AdminDepartment{})
	if repo.Find(hasSame, "is_deleted = 0 AND pid = ? AND name = ?", reqData.Pid, reqData.Name) && hasSame.Id != 0 {
		response.FailJson(ctx, "同级下已存在同名部门", nil)
		return
	}

	if !repo.Create(reqData) {
		response.FailJson(ctx, "添加失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "添加成功", nil)
}

// Update 部门编辑
func (c *DepartmentController) Update(ctx *gin.Context) {
	reqData := &models.AdminDepartment{}
	rules := validator.NewRules(
		validator.NewRule("id", "部门ID", true, validator.TypeNumberNoneZero),
		validator.NewRule("name", "部门名称", true, validator.TypeNoEmpty),
		validator.NewRule("banner", "部门Banner图", true, validator.TypeLink),
		validator.NewRule("description", "部门简介", false, validator.TypeNoEmpty),
		validator.NewRule("pid", "所属部门", true, validator.TypeNumber),
		validator.NewRule("sort", "排序", true, validator.TypeNumber),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	// 检查重名
	hasSame := &models.AdminDepartment{}
	repo := repository.New(&models.AdminDepartment{})
	if repo.Find(hasSame, "is_deleted = 0 AND pid = ? AND name = ? AND id <> ?", reqData.Pid, reqData.Name, reqData.Id) && hasSame.Id != 0 {
		response.FailJson(ctx, "同级下已存在同名部门", nil)
		return
	}

	// 检查部门状态
	hasDepartment := &models.AdminDepartment{}
	if !repo.Find(hasDepartment, "is_deleted = 0 AND id = ?", reqData.Id) || hasDepartment.Id == 0 {
		response.FailJson(ctx, "部门信息已失效", nil)
		return
	}

	// 更新字段
	refObj, err := reflects.NewObject(hasDepartment)
	if err != nil {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}
	fields := []string{"name", "banner", "description", "pid", "sort"}
	refObj.BatchSetValueFromFields(fields, reqData)
	hasDepartment.UpdatedAt = response.Time(time.Now().Local())

	if !repo.UpdateById(reqData.Id, hasDepartment) {
		response.FailJson(ctx, "编辑失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "编辑成功", nil)
}

// Delete 部门删除
func (c *DepartmentController) Delete(ctx *gin.Context) {
	reqData := &models.AdminDepartment{}
	rules := validator.NewRules(
		validator.NewRule("id", "部门ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	repo := repository.New(&models.AdminDepartment{})
	hasDepartment := &models.AdminDepartment{}
	if !repo.Find(hasDepartment, "is_deleted = 0 AND id = ?", reqData.Id) || hasDepartment.Id == 0 {
		response.FailJson(ctx, "部门信息已失效", nil)
		return
	}

	if !repo.DeleteById(reqData.Id) {
		response.FailJson(ctx, "删除失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "删除成功", nil)
}

// Disable 部门禁用
func (c *DepartmentController) Disable(ctx *gin.Context) {
	reqData := &models.AdminDepartment{}
	rules := validator.NewRules(
		validator.NewRule("id", "部门ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	repo := repository.New(&models.AdminDepartment{})
	hasDepartment := &models.AdminDepartment{}
	if !repo.Find(hasDepartment, "is_deleted = 0 AND id = ? AND status = 1", reqData.Id) || hasDepartment.Id == 0 {
		response.FailJson(ctx, "部门信息已失效", nil)
		return
	}

	if !repo.DisableById(reqData.Id) {
		response.FailJson(ctx, "操作失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "操作成功", nil)
}

// Enable 部门启用
func (c *DepartmentController) Enable(ctx *gin.Context) {
	reqData := &models.AdminDepartment{}
	rules := validator.NewRules(
		validator.NewRule("id", "部门ID", true, validator.TypeNumberNoneZero),
	)
	if !validator.ShouldBindFromPostForm(ctx, reqData, rules...) {
		return
	}

	repo := repository.New(&models.AdminDepartment{})
	hasDepartment := &models.AdminDepartment{}
	if !repo.Find(hasDepartment, "is_deleted = 0 AND id = ? AND status = 0", reqData.Id) || hasDepartment.Id == 0 {
		response.FailJson(ctx, "部门信息已失效", nil)
		return
	}

	if !repo.EnableById(reqData.Id) {
		response.FailJson(ctx, "操作失败, 请稍后再试", nil)
		return
	}

	response.SuccessJson(ctx, "操作成功", nil)
}

// Options 部门选项列表
func (c *DepartmentController) Options(ctx *gin.Context) {
	departmentList := make([]models.AdminDepartment, 0)
	repo := repository.New(&models.AdminDepartment{})
	if !repo.SelectAll("sort ASC, created_at DESC", &departmentList, "status = 1 AND is_deleted = 0") {
		response.FailJson(ctx, "查询失败, 请稍后再试", nil)
		return
	}

	type departmentOption struct {
		Value int64  `json:"value"`
		Label string `json:"label"`
		Icon  string `json:"icon"`
	}

	result := make([]departmentOption, 0)
	for _, v := range departmentList {
		result = append(result, departmentOption{
			Value: v.Id,
			Label: v.Name,
			Icon:  v.Banner,
		})
	}

	response.SuccessJson(ctx, "查询成功", result)
}
